
import { cloneDeep, debounce, get, set, has, isArray, isString} from 'lodash'
import md5 from 'md5'
const cache = {

}
export default {
  props: {
    mode: {
      default: 'edit' // 编辑模式和 edit， 展示模式 view
    },
    settings: {
      type: Object,
      default: () => {}
    },
    value: {
      default: null,
    },
    cleanWhenNoMatch:{ // options中无与当前value匹配值时, 清空表单框(现为"过滤条件变更时"默认直接清空)
      default: true,
    },
    separator: {
      default:',',
    },
    entityModel:{
      default:null,
    },
    isInChildren:{
      default:false,
    },
    readonly:{
      default:false,
    },
    disabled: {
      type: Boolean,
      default: false 
    }
  },

  data() {
    return {
      options: null,
      loading: false,
      test:[],
      nullEntityModel: {id: null},
      lastFilter: null,
      isFirstChange: 0,
      dataId: null
    }
  },
  computed: {

  
    finalDisabled(){ // 综合计算最终的disabled 状态
      if(this.disabled || this.readonly){ // 外部控制优先级最高, 且不需要做任何操作
        return true
      }
      const { type, parentCode, selectDisabled, condition } = this.settings
      let disabled = false
      if (selectDisabled ) { 
        if (type === 'dict' && (!parentCode || parentCode === '' || parentCode === 'null' || parentCode === 'undefined')) {
          // 需要判断勾选了“过滤条件为空时禁用”
          if(selectDisabled) {
            disabled = true
          }
        } else if (type === 'entity') {
          // 暂时只处理了“且”的场景
          let finalCondition = get(condition ,'and.items',[])
          const hasNonValue = finalCondition.some(c => {
            let propertyValueIsNull = !c.propertyValue || c.propertyValue === ''
            // 如果绑定的是对象
            if (Object.prototype.toString.call(c.propertyValue) === '[object Object]') {
              propertyValueIsNull = Object.keys(c.propertyValue).every(key => !c.propertyValue[key])
            }
            return propertyValueIsNull
          })
          if (finalCondition.length && hasNonValue) {
            let bindValueIsNull = !this.value
            if (Object.prototype.toString.call(this.value) === '[object Object]') {
              bindValueIsNull = Object.keys(this.value).every(key => !this.value[key])
            }
            if(selectDisabled){
              disabled = true
              this.$emit('input', null)
            }
          }
        }
      }
      return disabled
    },

    isMultiple(){
      return this.$attrs.multiple || this.$attrs.multiple === '' || this.isCheckbox
    },
    isFilterable() {
      return this.$attrs.filterable || this.$attrs.filterable === ''
    },
    isClearable() {
      return this.$attrs.clearable || this.$attrs.clearable === ''
    },
    isSelect(){
      return this.$options._componentTag === 'PmSelect'|| this.$options._componentTag === 'pm-select'
    },
    isCheckbox(){
      return this.$options._componentTag === 'PmCheckboxGroup'|| this.$options._componentTag === 'pm-checkbox-group'
    },
    showContent() {
      // 如果绑定的是对象, 直接显示 label 字段
      if(this.settings){
        console.log('this.entityModel', this.entityModel, this.value)
        let {bindType = 'value', labelField} = this.settings
        if(bindType === 'entity'){
         if(Array.isArray(this.entityModel)){
          return this.entityModel.map(em => this.getLabel(em, labelField,'')).join(this.separator)
         }
         return this.entityModel ? this.getLabel(this.entityModel, labelField,'') : null
        }
      }
      if(Array.isArray(this.valueKey)){
        if(this.options){
          return this.options.filter(item => this.valueKey.includes(item.value)).map(item => item.label).join( this.separator)
        }
      } else {
        const selectedItem = this.options && this.options.find(item => item.value === this.valueKey)
        return selectedItem ? selectedItem.label : ''
      }
    },
    valueIsObject(){
      return !Array.isArray(this.value) && Object.prototype.toString.call(this.value) === '[object Object]'
    },
    valueKey:{
      get(){
        let value = cloneDeep(this.value)
        let {valueField} = this.settings
        if(this.valueIsObject){
          return value ? value[valueField] : null
        } else {
          if(this.isMultiple){
            if(value){
              if(Array.isArray(value)){
                return value
              } else {
                return value.toString().split(this.separator)
              }
            }else{
              return []
            }
          }else{
            return value
          }
        }
      },
      set(val){
        let {bindType = 'value', type} = this.settings
        if(bindType === 'entity' ) {
          // debugger
          if(val === null || val === undefined){
            this.updateEntityModel(cloneDeep(this.nullEntityModel))
          } else {
            if(Array.isArray(val)){
            }else{
              this.updateEntityModel()
            }
          }
        } else {
          if(Array.isArray(val)&&val){
          } else {
          }
          this.updateEntityModel()
        }
        
        if(this.$listeners.change){
          // this.$listeners.change(val)
          this.$emit('change',val)
      
        }
      
      }
    },
    selectedItem(){
      return this.options ? this.options.filter(item => Array.isArray(this.valueKey) ? this.valueKey.includes(item.value) : item.value === this.valueKey) : []
    },
    dispatchProxy(){
      if (Vue.prototype.dispatchProxy) {
        return Vue.prototype.dispatchProxy(this)
      } else {
        return this.dispatch
      }
    },
    bus(){
      return this.$bus || this.$BaseBus
    }
  },
  watch: {
    'settings': {
      immediate:true,
      deep: true,
      handler (val, oVal) {
        if (JSON.stringify(val) !== JSON.stringify(oVal)) {
          this.showAll = false
          this.isFirstChange ++
          this.initDefault(this.$options.name === 'pm-select') // pm-select 开启懒加载
        }
      }
    },
    value(val) {
      if (!val) {
        const { type, parentCode, selectDisabled, condition } = this.settings
        if (selectDisabled && !this.disabled && !this.readonly) {
          // 在此复写禁用方法是为了区分“变更”和“清空操作”
          if (type === 'entity') {
            let finalCondition = get(condition ,'and.items',[])
            this.$attrs.disable = finalCondition.some(c => {
              let valueIsNull = !c.propertyValue || c.propertyValue === ''
              // 如果绑定的是对象
              if (Object.prototype.toString.call(c.propertyValue) === '[object Object]') {
                valueIsNull = Object.keys(c.propertyValue).every(key => !c.propertyValue[key])
              }
              return valueIsNull
            })
          } else if (type === 'dict' && !parentCode) {
            this.$attrs.disabled = true
          }
        }
      }
    },
    // selectedItem:{
    //   deep:true,
    //   handler(val){
    //     if(val.length === 1){
    //       this.$emit('update:entityModel', cloneDeep(val[0]))
    //     }else{
    //       this.$emit('update:entityModel', cloneDeep(val))
    //     }
    //     // console.log('update:entityModel', val)
    //     // this.$emit('update:entityModel', val)
    //   }
    // }
  },
  created() {
    // this.initDefault(this.$options.name === 'pm-select')
  },
  methods: {
    setDefaultModelObject(){
      if(this.valueKey !== '' && this.valueKey !== null && this.valueKey !== undefined && this.valueKey.length !== 0){
        this.updateEntityModel()
      }
    },
    
    getValue(item, valueField, defaultValue = null){
      if(valueField){
        return item[valueField] || defaultValue
      }else{
        if(item.code !== undefined){
          return item.code || defaultValue
        }
        if(item.value !== undefined){
          return item.value || defaultValue
        }
        if(item.id !== undefined){
          return item.id || defaultValue
        }
      }
      return null
    },
    getLabel(item, labelField, defaultLabel = null){
      if(labelField){
        return item[labelField] || defaultLabel
      }else{
        if(item.name !== undefined){
          return item.name || defaultLabel
        }
        if(item.label !== undefined){
          return item.label || defaultLabel
        }
      }
      return null
    },
    updateEntityModel(obj){
      this.$nextTick(()=>{
        if(this.selectedItem.length === 1){
          const newObj = obj || cloneDeep(this.selectedItem[0]._data)
          this.$emit('update:entityModel', newObj)
        } else {
          const newObj = obj || cloneDeep(this.selectedItem.map(s => s._data))
          this.$emit('update:entityModel', newObj)
        }
      })
    },
    setOptions(options){
      const { labelField, valueField  } = this.settings
      this._setOptions(options.map(op => {
        return {
          value: this.getValue(op,valueField),
          label: this.getLabel(op,labelField),
        }
      }))
    },
    _setOptions(options){
      // debugger
      this.options = options
      const { type, selectDisabled, parentCode, condition } = this.settings
      // 1. [数据来源type为“字典”或“实体”]cleanWhenNoMatch为true且联动后的options不存在与当前选中值匹配的项时, 清空联动目标选中值
      if(this.cleanWhenNoMatch && (type === 'dict' || type === 'entity') && !!this.value) {
        // valueKey判断当前是单选or多选
        if (isString(this.valueKey) && !this.options.some(op => op.value === this.valueKey)) {
        } else if (isArray(this.valueKey) && this.valueKey.length) {
          // const currentValueArr = this.options.filter(item => this.valueKey.includes(item.value)).map(op => op.value)
          // this.$emit('input', currentValueArr.join())
        }
      }
      // // 2. 配置勾选了“过滤条件为空时禁用”-selectDisabled时, 联动目标输入框清空并禁用(由于改动值会影响输入框的启禁用状态, 所以在value监听事件中, 使值先清空再禁用)
      // if (selectDisabled && !this.disabled && !this.readonly) { // 只读状态为最高状态判断级别
      //   if (type === 'dict' && (!parentCode || parentCode === '' || parentCode === 'null' || parentCode === 'undefined')) {
      //     // 需要判断勾选了“过滤条件为空时禁用”
      //     !this.value ? this.$attrs.disabled = selectDisabled 
      //               : this.cleanWhenNoMatch ? this.$emit('input', null) : null
      //   } else if (type === 'entity') {
      //     // 暂时只处理了“且”的场景
      //     let finalCondition = get(condition ,'and.items',[])
      //     const hasNonValue = finalCondition.some(c => {
      //       let propertyValueIsNull = !c.propertyValue || c.propertyValue === ''
      //       // 如果绑定的是对象
      //       if (Object.prototype.toString.call(c.propertyValue) === '[object Object]') {
      //         propertyValueIsNull = Object.keys(c.propertyValue).every(key => !c.propertyValue[key])
      //       }
      //       return propertyValueIsNull
      //     })
      //     if (finalCondition.length && hasNonValue) {
      //       let bindValueIsNull = !this.value
      //       if (Object.prototype.toString.call(this.value) === '[object Object]') {
      //         bindValueIsNull = Object.keys(this.value).every(key => !this.value[key])
      //       }
      //       bindValueIsNull ? this.$attrs.disabled = selectDisabled 
      //               : this.cleanWhenNoMatch ? this.$emit('input', null) : null
      //     } else {
      //       this.$attrs.disabled = false
      //     }
      //   }
      // }
    },
    pointFilter(){
      const { type, dictTypeCode, entity, parentCode, cascade, action, 
        condition, dataField = null, params } = this.settings
        if(type === 'entity'){
          let finalCondition = get(condition ,'and.items',[])
          set(condition,'and.items',finalCondition.filter(c => c.propertyValue !== 'null'))
          return  get(condition ,'and.items',[]).length > 0 ? condition: null
        }else if(type === 'dict'){
          return {dictTypeCode, parentCode}
        }
    },
    getOptions(){
      return this.options
    },
    initDefault(lazy = false) {
      // debugger
      // debugger
      // 当绑定值为对象时初始化对象模型, 用于清空时回填
      if( !Array.isArray(this.value) && Object.prototype.toString.call(this.value) === '[object Object]'){
        this.nullEntityModel = cloneDeep(this.value)
        Object.keys(this.nullEntityModel).forEach(key => {
          this.nullEntityModel[key] = null
        })
      }
      const { type = 'dict', options, labelField = 'label', valueField = 'value',disabledField = 'disabled', cascaderField='', labelIsFormatted = false, descriptionField = 'description' } = this.settings
      // 静态数据优先
      if(options && Array.isArray(options)){
        this._setOptions(options.map(item =>{
          if(typeof item === 'string'){
            return {
              label: item,
              value: item,
            }
          } else {
            return {
              // label: labelIsFormatted && get(item, descriptionField) ? `${get(item, descriptionField, 'description')}(${get(item, labelField || 'name')})`
              // : get(item, labelField  || 'name'),

              label: labelIsFormatted && get(item, descriptionField) ? `${get(item, descriptionField, 'description')}(${this.getLabel(item, labelField)})`
                                      : this.getLabel(item, labelField),
              value: this.getValue(item, valueField),
              disabled: get(item, disabledField || 'disabled'),
              _data:item,
            }
          }
        }))
        console.log('===========', this.options)
        return
      }

      if(lazy) {
        if(!this.value && this.isSelect){ // 开启缓存后 如果 value 为空 则 option 直接设置为 [], 阻断请求
          this._setOptions([])
          return
        }
        if(this.entityModel){
          if(type !== 'dict'){
            if(this.isFirstChange > 1 || (this.lastFilter !== null && JSON.stringify(this.lastFilter) !== JSON.stringify(this.pointFilter()))){ // 如果筛选条件发生变化, 则直接清空 options 和 value
              this._setOptions([])
              this.valueKey = null
              return
            }
          }
          console.log('懒加载数据...')
          if(this.isMultiple && this.entityModel.length > 0){
            this._setOptions(this.entityModel.map(em => {
              return {
                value: this.getValue(em,valueField),
                label: this.getLabel(em,labelField),
                _data: em,
              }
            }))
            return
          } else if ( this.entityModel[valueField]&& this.entityModel[labelField]){
              this._setOptions([{
                value: this.getValue(this.entityModel, valueField), 
                label: this.getLabel(this.entityModel, labelField),
                _data:this.entityModel,
              }])
              return
          } else if(this.settings.type === 'dict'){
            if(this.entityModel['code'] || this.entityModel['name']){
              this._setOptions([{
                value:this.entityModel['code'], 
                label:this.entityModel['name'],
                _data:this.entityModel,
              },  
                ])
              return
            }
          }
        }
      }else{
        console.log('加载全部数据...')
      }
      
       // 动态数据
      const dataId = md5(JSON.stringify(this.settings)).substring(0, 10)
      this.dataId =dataId
      if (cache[dataId]) {
        if (cache[dataId].loading) {
          this.bus.$on(`data:${dataId}`, (data) => {
            this._setOptions(data)
          })
        } 
        return
      } else {
        cache[dataId] = {
          loading: true
        }
      }
      
      const { dictTypeCode, entity, parentCode, cascade, action, 
        condition, dataField = null, params } = this.settings

      this.lastFilter = this.pointFilter()  // 记录本次筛选条件
      if (this.settings.type === 'dict' && dictTypeCode) {
        this.loading = true
        let response = this.dispatchProxy( Vue.prototype.Controllers.DictEntryController.queryDictEntrysByCriteria, {
          ...this.lastFilter,
          pageSize:0,
          pageIndex:0,
        })
        response.then(data => {
          if(has(data,'error'))
          data = data.data
          if(data){
            this._setOptions(data.data.map(item => {
              return {
                label: item.name,
                value: item.code,
                _data: item,
                disabled: get(item, disabledField || 'disabled'),
              }
            }))
            console.log(this.options,'options')
            this.bus.$emit(`data:${dataId}`, this.options)
            this.setDefaultModelObject()
            delete cache[dataId]
          }
          this.loading = false
        })
        if(response.end){
          response.end(d => {
            this.loading = false
          })
        }
      } else if (this.settings.type === 'entity' && entity) {
        this.loading = true
      
        // 处理 condition
        let response = this.dispatchProxy(Vue.prototype.Controllers.LowcodeModelController.queryWithPage, {
          params: {
            entityName: entity,
          },
          payload: {
            condition : this.lastFilter
          }
        })
        response.then(data => {
          if(has(data,'error'))
           data = data.data
          if(data){
            this._setOptions(data.data.map(item => {
              return {
                label: this.getLabel(item, labelField),
                value: this.getValue(item, valueField),
                disabled: get(item, disabledField || 'disabled'),
                _data: item,
              }
            }))
          
            this.bus.$emit(`data:${dataId}`, this.options)
            this.setDefaultModelObject()
            delete cache[dataId]
          }
          this.loading = false
        })
        if(response.end){
          response.end(d => {
            this.loading = false
          })
        }

      } else if (action) {
        this.loading = true
        this.dispatchProxy(action, params).then(data => {
          if(has(data,'error'))
          data = data.data
          this._setOptions(([...(dataField ? data[dataField] : data)] || []).map(item => {
            return {
              label: get(item,labelField|| 'name'),
              value: get(item, valueField|| 'id',''),
              disabled: get(item, disabledField || 'disabled'),
              _data: item,
            }
          }))
          this.bus.$emit(`data:${dataId}`, this.options)
          this.setDefaultModelObject()
          delete cache[dataId]
        }).end(d => {
          this.loading = false
        })
      }
    },
  },
  beforeDestroy() {
    this.bus.$off(`data:${this.dataId}`)
  },
}
